<template>
  <el-row style="margin-right: -15px">
    <el-col :span="19">
      <div style="display: flex">
        <el-button-group>
          <el-button type="primary" :icon="FolderChecked" @click="update" :loading="saving">保存</el-button>
          <el-button type="success" :icon="View" @click="onPreview">预览</el-button>
        </el-button-group>
        <el-dropdown>
          <el-button type="primary">
            <el-icon><MoreFilled /></el-icon>
          </el-button>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item :icon="CopyDocument" @click="handleOpenVersionDialog('saveAs')">
                另存版本
              </el-dropdown-item>
              <el-dropdown-item :icon="Files" @click="handleOpenVersionDialog('manage')">版本管理</el-dropdown-item>
              <el-dropdown-item :icon="Delete" @click="clear">清空表单</el-dropdown-item>
              <el-dropdown-item :icon="DocumentCopy" @click="handleOpenVersionDialog('clone')">
                克隆表单
              </el-dropdown-item>
              <el-dropdown-item :icon="FolderOpened" divided>导入模版</el-dropdown-item>
              <el-dropdown-item :icon="FolderAdd">保存为模版</el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
      <el-row>
        <el-col :span="6" class="define-pane" :style="`height: ${leftHeight}`">
          <div v-for="(c, i) in config" :key="i">
            <div v-if="c.list && c.list.length > 0" class="define-category-name">
              <el-icon><Menu /></el-icon> {{ c.name }}
            </div>
            <el-row>
              <el-col :span="12" v-for="(item, i) in c.list" :key="i" style="padding: 5px 10px 5px 0">
                <draggable
                  :list="[item]"
                  :sort="false"
                  :group="{ name: 'comp', pull: 'clone', put: false }"
                  item-key="index"
                  @start="state.drag = true"
                  @end="state.drag = false"
                  :clone="onCloneDragItem"
                >
                  <template #item="{ element }">
                    <div class="define-item" @click="onClickAddComp(element)">
                      <al-icon :icon="element.icon" style="margin-right: 5px; width: 1.2em; height: 1.2em" />
                      {{ element.label }}
                    </div>
                  </template>
                </draggable>
              </el-col>
            </el-row>
          </div>
        </el-col>
        <el-col :span="18" class="design-pane">
          <label class="form-title">{{ fs.form.title }}</label>
          <div class="form-wrap" :style="`height: ${centerHeight};`">
            <el-form
              :size="fs.form.size"
              :label-position="fs.form.labelPosition"
              :label-width="`${fs.form.labelWidth}px`"
            >
              <draggable
                v-model="fs.comps"
                class="design-area"
                ghost-class="ghost"
                tag="el-row"
                :style="`min-height: 48px`"
                :group="{ name: 'comp' }"
                :animation="300"
                item-key="id"
                @add="onAddDragItem"
                @update="onUpdateDragItem"
              >
                <template #header v-if="fs.comps.length === 0 && !state.drag">
                  <el-col :span="24">
                    <el-empty description="从左侧拖入或点选组件进行表单设计" />
                  </el-col>
                </template>
                <template #item="{ element, index }">
                  <el-col
                    :style="colStyle"
                    :span="element.propsData.col"
                    :class="`comp ${index === fs.currComp.index ? 'active' : ''}`"
                    @click.stop="fs.activeComp(index)"
                  >
                    <RenderComp
                      :comp="element"
                      @copy="onCopyComp(index)"
                      @remove="onRemoveComp(index)"
                      @click="onClickComp"
                    />
                  </el-col>
                </template>
              </draggable>
            </el-form>
          </div>
        </el-col>
      </el-row>
    </el-col>
    <el-col :span="5">
      <el-tabs v-model="state.currPaneName" stretch style="margin-top: -10px; padding-right: 5px">
        <el-tab-pane label="组件属性" name="comp" class="comp-props" :style="`height: ${rightHeight}; `">
          <RenderProps v-if="fs.currComp.index >= 0" />
        </el-tab-pane>
        <el-tab-pane label="组件权限" name="auth" class="comp-props" :style="`height: ${rightHeight}; `">
          <PermissionComp v-if="fs.currComp.index >= 0" />
        </el-tab-pane>
        <el-tab-pane label="表单属性" name="form" class="form-props" :style="`height: ${rightHeight}; `">
          <FormProps />
        </el-tab-pane>
      </el-tabs>
    </el-col>
    <DialogVersion
      :formId="fs.designData.formId"
      :mode="state.versionDialogMode"
      ref="refVersionList"
      v-model:visible="state.versionVisible"
    />
  </el-row>
</template>

<script setup lang="ts">
import { computed, reactive } from 'vue'
import { useRouter } from 'vue-router'
import {
  Menu,
  Delete,
  FolderChecked,
  DocumentCopy,
  View,
  MoreFilled,
  Files,
  FolderOpened,
  FolderAdd,
  CopyDocument
} from '@element-plus/icons-vue'
import { ElForm, ElEmpty, ElTabs, ElTabPane, ElDropdown, ElDropdownMenu, ElDropdownItem } from 'element-plus'
import { util } from '@/utils'
import draggable from 'zhyswan-vuedraggable'
import { useFlowStore } from '@/stores/flow'
import { config, defaultProps, getPermissionConfig } from '../comps/config'
import RenderComp from './render/Comp.vue'
import RenderProps from './render/Props.vue'
import FormProps from '../form-props/Props.vue'
import PermissionComp from './render/Permission.vue'
import { useDesign } from './hooks'
import DialogVersion from '../supports/DialogVersion.vue'
import type { VersionDialogType } from '@/typings'

const state = reactive({
  drag: false, //拖动状态
  currPaneName: 'comp',

  cleared: false,
  versionVisible: false,
  versionDialogMode: '' as VersionDialogType
})

const leftHeight = computed(() => `${util.getContentHeight() - 70}px`)
const centerHeight = computed(() => `${util.getContentHeight() - 55}px`)
const rightHeight = computed(() => `${util.getContentHeight() - 65}px`)

const router = useRouter()
const fs = useFlowStore()

const { update, clear, saving, getInitPermission } = useDesign()

const colStyle = computed(() => {
  const margin = `margin-top: ${fs.form.rowSpacing / 2}px; margin-bottom: ${fs.form.rowSpacing / 2}px;`
  const border = `border: 1px dashed ${fs.form.showCompBorder ? '#dcdfe6' : 'transparent'}`
  return `${margin}${border}`
})

const onCloneDragItem = (dragItem: any) => {
  return {
    config: dragItem,
    propsData: { field: `comp_${util.randomWord(6)}`, ...defaultProps(dragItem) },
    permission: { ...getInitPermission(dragItem) },
    permissionConfig: { ...getPermissionConfig(dragItem) }
  }
}
//点击左侧comp添加组件
const onClickAddComp = (compConfig: any) => {
  fs.comps.push(onCloneDragItem(compConfig))
  fs.activeComp(fs.comps.length - 1)
}
//拖拽添加组件
const onAddDragItem = (dragItem: any) => {
  fs.activeComp(dragItem.newIndex)
}
//移动设计区组件
const onUpdateDragItem = (dragItem: any) => {
  //移动跨越了当前激活组件，需要重新激活
  if (dragItem.oldIndex === fs.currComp.index) {
    fs.activeComp(dragItem.newIndex)
  } else if (
    (dragItem.oldIndex <= fs.currComp.index && fs.currComp.index <= dragItem.newIndex) ||
    (dragItem.oldIndex >= fs.currComp.index && fs.currComp.index >= dragItem.newIndex)
  ) {
    if (dragItem.oldIndex < dragItem.newIndex) {
      //下移
      fs.activeComp(fs.currComp.index - 1)
    } else {
      //上移
      fs.activeComp(fs.currComp.index + 1)
    }
  }
}
//copy组件
const onCopyComp = (index: number) => {
  fs.comps.splice(index, 0, fs.comps[index])
}
//删除组件
const onRemoveComp = (index: number) => {
  fs.comps.splice(index, 1)
}
const onClickComp = () => {
  if (state.currPaneName === 'form') {
    state.currPaneName = 'comp'
  }
}
const handleOpenVersionDialog = (type: VersionDialogType) => {
  state.versionDialogMode = type
  state.versionVisible = true
}
const onPreview = () => {
  router.push({ name: 'flw-def-form-preview', query: { id: fs.designData.formId } })
}
</script>

<style lang="scss" scoped>
:deep(.el-button-group) {
  .el-button:last-child {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    margin-right: 0.5px;
  }
}
:deep(.el-dropdown) {
  .el-button:first-child {
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
  }
}
.define-pane {
  margin-top: 15px;
  border-right: 1px solid $--color-border-1level;
  .define-category-name {
    display: flex;
    align-items: center;
    gap: 2px;
    &:nth-child(n + 1) {
      margin-top: 10px;
    }
  }
  .define-item {
    width: 100%;
    height: 28px;
    display: flex;
    align-items: center;
    padding: 5px 11px;
    border: 1px dashed transparent;
    border-radius: 3px;
    background: $--color-border-4level;
    font-size: $--size-font-x-small;
    cursor: move;
    &:hover,
    &:focus {
      border: 1px dashed $--color-primary;
      color: $--color-primary;
    }
  }
}
.design-pane {
  margin-top: -30px;
  .form-wrap {
    padding: 0 10px;
    overflow-y: auto;
  }
  .form-title {
    display: block;
    text-align: center;
    font-weight: bold;
    font-size: $--size-font-x-large;
  }
  .design-area {
    padding-top: 10px;
    overflow-y: auto;
    .comp {
      padding: 8px;
      margin-left: 0;
      margin-right: 0;
      transition-property: all;
      transition-duration: 0.2s;
      &:hover,
      &:focus,
      &.active {
        background-color: $--color-border-4level;
        cursor: move;
        :deep(.bar) {
          display: inline-block;
        }
      }
      :deep(.el-form-item) {
        margin-bottom: 0;
      }
    }
    .ghost {
      padding: 8px 15px;
      width: 100%;
      border: 2px dashed $--color-success;
    }
  }
}
.comp-props,
.form-props {
  border-left: 1px solid $--color-border-1level;
  overflow-y: auto;
  padding-right: 10px;
}
</style>
